package com.njuse.jvmfinal.Instruction;

import java.nio.ByteBuffer;

import com.njuse.jvmfinal.memory.jclass.AccessFlags;
import com.njuse.jvmfinal.memory.jclass.Method;
import com.njuse.jvmfinal.memory.jclass.runtimeConstantPool.constant.ref.MethodRef;
import com.njuse.jvmfinal.runtimestructure.Jframe;
import com.njuse.jvmfinal.runtimestructure.Jobject;

public class INVOKE_VIRTUAL extends Instruction {
	private int index;
	public void readindex(ByteBuffer reader) {
		this.index=(int)reader.getShort();
	}
	
	public void execute(Jframe frame) {
		MethodRef methodref=(MethodRef)frame.getMymethod().getClazz().getRuntimeConstantPool().getConstant(index);
		Method method=methodref.findmethod();
        if ((method.accessFlags & AccessFlags.ACC_NATIVE)!=0) return;
        int argc = method.getArgc(); 
        Object[] argv = new Object[argc];
        for (int i = 0; i < argc; i++) {
        	int top=frame.getStacktop();
        	top--;
            argv[i] = frame.getManagestack()[top];
            frame.setStacktop(top);
        }   
        Object[] localvars=new Object[method.getMaxLocal()+1];
        for (int i = 1; i <argc+1; i++) {
            localvars[i]=argv[argc - i];
        }
        int top=frame.getStacktop();
        Jobject temp=(Jobject) frame.getManagestack()[top-1];
        top--;
        localvars[0]=temp;
        frame.setStacktop(top);
        Method invoke=methodref.findmethod(temp.getClazz());
        Jframe newframe = new Jframe(frame.getMythread(), invoke,invoke.getMaxStack(), invoke.getMaxLocal() + 1);
        newframe.setLocal(localvars);
        frame.getMythread().push(newframe);
	}
	
}
